/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.webapp.util.core;

import com.blandware.atleap.common.util.Folder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
 * <p>Contains information about page folder, which is virtual and does not exist in database.</p>
 * <p><a href="VirtualFolder.java.html"><i>View Source</i></a></p>
 *
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.6 $ $Date: 2007/12/18 18:11:52 $
 */
public class VirtualFolder implements Folder {

	protected transient final Log log = LogFactory.getLog(VirtualFolder.class);

	/**
	 * Name of this folder. In form, for example, baz
	 */
	protected String name;

	/**
	 * Path to this folder from the root. In form, for example, /foo/bar,
	 * so full path to this folder will be /foo/bar/baz
	 */
	protected String path;

	/**
	 * Delimiter between folder names
	 */
	protected char delimiter = '/';

    /**
     * Whether this is root folder
     */
    protected boolean parentFolder = false;

    /**
	 * Creates new instance of VirtualFolder with a given name
	 *
	 * @param name Name of this folder
	 */
	public VirtualFolder(String name) {
		this(name, '/');
	}

	/**
	 * Creates new instance of VirtualFolder with a given name and path
	 *
	 * @param name Name of this folder
	 * @param path Path to this folder
	 */
	public VirtualFolder(String name, String path) {
		this(name, path, '/');
	}

	/**
	 * Creates new instance of VirtualFolder with a given name and folder delimiter
	 *
	 * @param name      Name of this folder
	 * @param delimiter Delimiter between folder names
	 */
	public VirtualFolder(String name, char delimiter) {
		this.name = name;
		this.delimiter = delimiter;
	}

	/**
	 * Creates new instance of VirtualFolder with a given name, path and a folder
     * delimiter
	 *
	 * @param name      Name of this folder
	 * @param path      Path to this folder
	 * @param delimiter Delimiter between folder names
	 */
	public VirtualFolder(String name, String path, char delimiter) {
		this.name = name;
		this.path = path;
		this.delimiter = delimiter;
	}

	/**
	 * Creates new instance of VirtualFolder with a given name, path, folder
     * delimiter and parent folder status
	 *
	 * @param name          Name of this folder
	 * @param path          Path to this folder
	 * @param delimiter     Delimiter between folder names
     * @param parentFolder  Whether this is root
	 */
	public VirtualFolder(String name, String path, char delimiter, boolean parentFolder) {
		this.name = name;
		this.path = path;
		this.delimiter = delimiter;
        this.parentFolder = parentFolder;
    }

    /**
     * Gets name of this virtual folder
     *
     * @return name
     */
	public String getName() {
		return name;
	}

    /**
     * Sets name of this virtual folder
     *
     * @param name name to set
     */
	public void setName(String name) {
		this.name = name;
	}

    /**
     * Gets path of this virtual folder
     *
     * @return path
     */
	public String getPath() {
		return path;
	}

    /**
     * Sets path of this virtual folder
     *
     * @param path path to set
     */
	public void setPath(String path) {
		this.path = path;
	}

    /**
     * Gets delimiter of this virtual folder
     *
     * @return delimiter
     */
	public char getDelimiter() {
		return delimiter;
	}

    /**
     * Sets delimiter of this virtual folder
     *
     * @param delimiter delimiter to set
     */
	public void setDelimiter(char delimiter) {
		this.delimiter = delimiter;
	}

    /**
     * Returns whether this is parent folder.
     *
     * @return whether this is parent folder
     */
    public boolean isParentFolder() {
        return parentFolder;
    }

    /**
     * Sets whether this is parent folder.
     *
     * @param parentFolder true if parent
     */
    public void setParentFolder(boolean parentFolder) {
        this.parentFolder = parentFolder;
    }

    /**
	 * Returns full path to the folder which is concatenation of path and name fields
	 *
	 * @return Full path to the folder
	 */
	public String getFullPath() {
		String fullPath = path;
		if ( !name.trim().equals("..") ) {
			fullPath += (path.length() > 1 ? String.valueOf(delimiter) : "") + name;
		}
		return fullPath;
	}

	/**
	 * Splits path by specified delimiter and returns list of virtual folders.
	 *
	 * @param path      Path to split
	 * @param delimiter Delimiter to split by
	 * @return List of virtual folders
	 */
	public static List splitPath(String path, char delimiter) {
		return splitPath(path, delimiter, true);
	}

	/**
	 * Splits path by specified delimiter and returns list of virtual folders.
     * For example, if "foo/bar/baz" is given as <code>path</code>, '/' as
     * <code>delimiter</code> and <code>startFromDelim</code> is
     * <code>false</code>, wi'll get <code>{"foo", "foo/bar", "foo/bar/baz"}</code>.
	 *
	 * @param path      Path to split
	 * @param delimiter Delimiter to split by
	 * @param startFromDelim Whether or not to begin string with delimiter
	 * @return List of virtual folders
	 */
	public static List splitPath(String path, char delimiter, boolean startFromDelim) {
		String delimiterString = String.valueOf(delimiter);
		List folders = new ArrayList();
		if ( path != null && path.length() > 0 ) {
			StringTokenizer pathElements = new StringTokenizer(path, delimiterString, false);
			String folderPath = startFromDelim ? delimiterString : "";
			while ( pathElements.hasMoreTokens() ) {
				String folderName = pathElements.nextToken();
				VirtualFolder virtualFolder = new VirtualFolder(folderName, folderPath, delimiter);
				folders.add(virtualFolder);
				folderPath += (folderPath.length() > 1 ? delimiterString : "") + folderName;
			}
		}
		return folders;
	}

	/**
	 * Splits path by '/' and returns list of virtual folders.
	 *
	 * @param path Path to split
	 * @return List of virtual folders
	 */
	public static List splitPath(String path) {
		return splitPath(path, '/');
	}


	public boolean equals(Object o) {
		if ( this == o ) {
			return true;
		}
		if ( !(o instanceof Folder) ) {
			return false;
		}

		final Folder folder = (Folder) o;

		if ( name != null ? !name.equals(folder.getName()) : folder.getName() != null ) {
			return false;
		}
		if ( path != null ? !path.equals(folder.getPath()) : folder.getPath() != null ) {
			return false;
		}

		return true;
	}

	/**
	 * Compares this folder to another. If specified object does not implement
	 * <code>com.blandware.atleap.common.util.Folder</code>, ClassCastException will be thrown
	 *
	 * @param o Object to compare with
	 * @return Negative integer if this folder is less than specified one, zero value if this folder is equal to specified and
	 *         positive integer if this folder is greater that specified one
	 * @see java.lang.Comparable#compareTo(Object)
	 * @see com.blandware.atleap.common.util.Folder
	 */
	public int compareTo(Object o) {
		if ( !(o instanceof Folder) ) {
			throw new ClassCastException("Cannot compare instance of " + getClass().getName() + " to the instance of " + o.getClass().getName());
		}
		Folder f = (Folder) o;
		return name.equalsIgnoreCase(f.getName()) ? path.compareToIgnoreCase(f.getPath()) : name.compareToIgnoreCase(f.getName());
	}

	public int hashCode() {
		int result;
		result = (name != null ? name.hashCode() : 0);
		result = 29 * result + (path != null ? path.hashCode() : 0);
		return result;
	}

	public String toString() {
		StringBuffer sb = new StringBuffer("VirtualFolder [");
		sb.append("name=").append(this.name);
		sb.append(", path=").append(this.path);
		sb.append("]");
		return sb.toString();
	}
}
